<?php

declare(strict_types=1);

namespace App\Resource\Controller;

use App\Common\Constants\ErrorCode;
use App\Common\Controller\AbstractController;
use App\Common\Middleware\JwtAuthMiddleware;
use App\Common\Middleware\PermissionMiddleware;
use App\Resource\Request\NavigationRequest;
use App\Resource\Service\NavigationService;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\DeleteMapping;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\HttpServer\Annotation\PutMapping;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Validation\Contract\ValidatorFactoryInterface;
use Hyperf\Validation\Rule;

/**
 * @Controller()
 */
class NoticeController extends AbstractController
{

    /**
     * @Inject()
     * @var NavigationService
     */
    private $navigationService;

    /**
     * @Inject()
     * @var ValidatorFactoryInterface
     */
    protected $validationFactory;

    const NOTICE = 4;

    /**
     * 公告列表
     * @RequestMapping(path="/v1/notice", methods="get")
     * @param RequestInterface $request
     * @Middlewares({
     *     @Middleware(JwtAuthMiddleware::class),
     *     @Middleware(PermissionMiddleware::class)
     * })
     *
     * @return array
     */
    public function index(RequestInterface $request)
    {
        $params = $request->all();
        $perPage = !empty($params['perpage']) ? $params['perpage'] : 15;
        $field = ['id', 'title', 'sort', 'status', 'created_at'];
        $res = $this->navigationService->getList($params, (int)$perPage, self::NOTICE, $field);
        if ($res['code']) {
            return $this->failed($res['code']);
        } else {
            return $this->success($res['data']->items(), '获取成功', $res['data']->total());
        }
    }

    /**
     * 获取公告详情
     * @RequestMapping(path="/v1/notice/{id:\d+}", methods="get")
     * @param int $id
     *
     * @return array
     */
    public function info(int $id, RequestInterface $request)
    {
        $shopType = $request->input('shop_type') ?? null;
        $field = ['id', 'title', 'content', 'sort'];
        $res = $this->navigationService->getInfoById($id, self::NOTICE, $field, $shopType);
        if (!$res['code']) {
            return $this->success($res['data'], '获取成功');
        } else {
            return $this->failed($res['code']);
        }
    }

    /**
     * 添加公告
     * @PostMapping(path="/v1/notice", methods="post")
     * @param NavigationRequest $request
     * @Middlewares({
     *     @Middleware(JwtAuthMiddleware::class),
     *     @Middleware(PermissionMiddleware::class)
     * })
     *
     * @return array
     */
    public function store(RequestInterface $request)
    {
        $validator = $this->validationFactory->make(
            $request->all(),
            [
                'title' => 'required|max:25|unique:hf_crd_navigation,title',
                'content' => 'required',
                'sort' => 'sometimes',
                'status' => 'sometimes',
            ],
            [],
            [
                'title' => '公告标题',
                'content' => '公告内容',
                'sort' => '排序权重',
            ]
        );
        if ($validator->fails()) {
            $errorMessage = $validator->errors()->first();
            return $this->failed(ErrorCode::PARAMS_INVALID, $errorMessage);
        }
        $res = $this->navigationService->add($request->all(), self::NOTICE);
        if (!$res['code']) {
            return $this->success($res['data'], '操作成功');
        } else {
            return $this->failed($res['code']);
        }
    }

    /**
     * 编辑公告
     * @PutMapping(path="/v1/notice/{id:\d+}", methods="put")
     * @param int $id
     * @param NavigationRequest $request
     * @Middlewares({
     *     @Middleware(JwtAuthMiddleware::class),
     *     @Middleware(PermissionMiddleware::class)
     * })
     *
     * @return array
     */
    public function update(int $id, RequestInterface $request)
    {
        $validator = $this->validationFactory->make(
            $request->all(),
            [
                'id' => 'required',
                'title' => [
                    'required',
                    'max:25',
                    Rule::unique('hf_navigation')->ignore($id),
                ],
                'content' => 'required',
                'sort' => 'sometimes',
                'status' => 'sometimes',
            ],
            [],
            [
                'title' => '公告标题',
                'content' => '公告内容',
                'sort' => '排序权重',
            ]
        );
        if ($validator->fails()) {
            $errorMessage = $validator->errors()->first();
            return $this->failed(ErrorCode::PARAMS_INVALID, $errorMessage);
        }
        $params = $request->all();
        $params['id'] = $id;
        $res = $this->navigationService->update($params, self::NOTICE);
        if (!$res['code']) {
            return $this->success($res['data'], '操作成功');
        } else {
            return $this->failed($res['code']);
        }
    }

    /**
     * 删除公告
     * @param RequestInterface $request
     * @DeleteMapping(path="/v1/notice/{id:\d+}", methods="delete")
     * @param int $id
     * @Middlewares({
     *     @Middleware(JwtAuthMiddleware::class),
     *     @Middleware(PermissionMiddleware::class)
     * })
     *
     * @return array
     */
    public function delete(int $id, RequestInterface $request)
    {
        $shopType = $request -> input('shop_type') ?? null;
        $res = $this->navigationService->delete($id, self::NOTICE, $shopType);
        if (!$res['code']) {
            return $this->success($res['data'], '操作成功');
        } else {
            return $this->failed($res['code']);
        }
    }

    /**
     * 禁用/启用
     * @PutMapping(path="/v1/notice/{id:\d+}/status", methods="put")
     * @param int $id
     * @Middlewares({
     *     @Middleware(JwtAuthMiddleware::class),
     *     @Middleware(PermissionMiddleware::class)
     * })
     *
     * @return array
     */
    public function editStatus(int $id, RequestInterface $request)
    {
        $shopType = $request->input('shop_type') ?? null;
        if (!$id) return $this->failed(ErrorCode::SYSTEM_INVALID);
        $res = $this->navigationService->editStatus('navigation', (int)$id, (string)self::NOTICE, $shopType);
        if (!$res['code']) {
            // TODO
            $this->navigationService->batchUpdateNavForRedis(self::NOTICE . '-');
            return $this->success($res['data'], '操作成功');
        } else {
            return $this->failed($res['code']);
        }
    }

    /**
     * 修改权重
     * @RequestMapping(path="/v1/notice/{id:\d+}/sort", methods="put")
     * @Middlewares({
     *     @Middleware(JwtAuthMiddleware::class),
     *     @Middleware(PermissionMiddleware::class)
     * })
     * @param int $id
     * @param RequestInterface $request
     *
     * @return array
     */
    public function editSort(int $id, RequestInterface $request)
    {
        $sort = $request->input('sort') ?? 0;
        if ($sort < 0 || $sort > 100) {
            return $this->failed(ErrorCode::SORT_INVALID);
        }
        $shopType = $request->input('shop_type') ?? null;
        $res = $this->navigationService->editSort($id, (int)$sort, $shopType);
        if (!$res['code']) {
            // TODO
            $this->navigationService->batchUpdateNavForRedis(self::NOTICE . '-');
            return $this->success($res['data'], '操作成功');
        } else {
            return $this->failed($res['code']);
        }
    }

    /**
     * 通知详情
     *
     * @RequestMapping(path="/v1/api/notice/{id:\d+}", methods="get")
     * @param int $id
     * @param RequestInterface $request
     *
     * @return array
     */
    public function noticeDetail(int $id)
    {
        $field = ['title', 'content'];
        $res = $this->navigationService->getInfoById($id, self::NOTICE, $field);
        if (!$res['code']) {
            return $this->success($res['data'], '获取成功');
        } else {
            return $this->failed($res['code']);
        }
    }
}
